package com.sne.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sne.sys.dto.SysRoleParamDTO;
import com.sne.sys.entity.*;
import com.sne.sys.service.ISysRoleDeptService;
import com.sne.sys.service.ISysRoleMenuService;
import com.sne.sys.service.ISysRoleService;
import com.sne.sys.service.ISysUserRoleService;
import com.sne.sys.dto.SysRoleDTO;
import com.sne.sys.mapper.SysRoleMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 角色 服务实现类
 * </p>
 *
 * @author fanghh
 * @since 2020-01-03
 */
@Slf4j
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements ISysRoleService {

    @Autowired
    private ISysUserRoleService iSysUserRoleService;

    @Autowired
    private ISysRoleDeptService iSysRoleDeptService;

    @Autowired
    private ISysRoleMenuService iSysRoleMenuService;

    @Override
    public List<SysRole> findRoleByUser(Long id) {
        List<SysRole> roleList = new ArrayList<>();
        List<SysUserRole> list = iSysUserRoleService.list(Wrappers.<SysUserRole>query()
                .lambda()
                .eq(SysUserRole::getUserId, id));
        if (CollectionUtils.isNotEmpty(list)) {
            List<Long> roleIdList = list.stream().map(SysUserRole::getRoleId).collect(Collectors.toList());
            roleList = this.list(Wrappers.<SysRole>query().lambda().in(SysRole::getId, roleIdList));
        }
        return roleList;
    }

    @Override
    public IPage<SysRole> findPage(Page page, SysRoleParamDTO role) {
        LambdaQueryWrapper<SysRole> queryWrapper = Wrappers.<SysRole>query().lambda();
        if(StringUtils.isNoneBlank(role.getRoleCode())){
            queryWrapper.like(SysRole::getRoleCode,role.getRoleCode());
        }
        if(StringUtils.isNoneBlank(role.getRoleName())){
            queryWrapper.like(SysRole::getRoleName,role.getRoleName());
        }
        if(role.getState() !=null){
            queryWrapper.eq(SysRole::getState,role.getState());
        }
        if(role.getStartTime() != null){
            queryWrapper.ge(SysRole::getCreateTime,role.getStartTime());
        }
        if(role.getEndTime() != null){
            queryWrapper.le(SysRole::getCreateTime,role.getEndTime());
        }
        return this.page(page,queryWrapper.orderByAsc(SysRole::getSort)
                .orderByDesc(SysRole::getCreateTime));
    }

    @Override
    public boolean checkUnique(SysRole role) {
        SysRole sysRole = this.getOne(Wrappers.<SysRole>query().lambda()
                .eq(SysRole::getRoleCode, role.getRoleCode()));
        return (sysRole == null || role.getId() != null) &&
                (sysRole == null || role.getId().equals(sysRole.getId()));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean delete(Long id) {
        iSysRoleDeptService.remove(Wrappers.<SysRoleDept>query().lambda().eq(SysRoleDept::getRoleId, id));
        iSysUserRoleService.remove(Wrappers.<SysUserRole>query().lambda().eq(SysUserRole::getRoleId, id));
        iSysRoleMenuService.remove(Wrappers.<SysRoleMenu>query().lambda().eq(SysRoleMenu::getRoleId, id));
        this.removeById(id);
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deleteIds(List<Long> ids) {
        iSysRoleDeptService.remove(Wrappers.<SysRoleDept>query().lambda().in(SysRoleDept::getRoleId, ids));
        iSysUserRoleService.remove(Wrappers.<SysUserRole>query().lambda().in(SysUserRole::getRoleId, ids));
        iSysRoleMenuService.remove(Wrappers.<SysRoleMenu>query().lambda().in(SysRoleMenu::getRoleId, ids));
        this.removeByIds(ids);
        return false;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean saveRole(SysRoleDTO role) {
        SysRole sysRole = new SysRoleDTO();
        BeanUtils.copyProperties(role,sysRole);
        this.save(sysRole);
        role.setId(sysRole.getId());
        this.saveRoleMenu(role);
        return true;
    }

    @Override
    public boolean updateRole(SysRoleDTO role) {
        SysRole sysRole = new SysRoleDTO();
        BeanUtils.copyProperties(role,sysRole);
        this.updateById(sysRole);
        iSysRoleMenuService.remove(Wrappers.<SysRoleMenu>query()
                .lambda().eq(SysRoleMenu::getRoleId,role.getId()));
        this.saveRoleMenu(role);
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean saveRoleMenu(SysRoleDTO role){
        List<SysRoleMenu> roleMenus = role.getMenuIds().stream().map(x -> {
            SysRoleMenu roleMenu = new SysRoleMenu();
            roleMenu.setMenuId(x).setRoleId(role.getId());
            return roleMenu;
        }).collect(Collectors.toList());
        iSysRoleMenuService.saveBatch(roleMenus);
        return true;
    }

    @Override
    public SysRoleDTO find(Long id) {
        SysRole role = this.getById(id);
        List<SysRoleMenu> roleMenus = iSysRoleMenuService.list(Wrappers.<SysRoleMenu>query()
                .lambda().eq(SysRoleMenu::getRoleId, id));
        List<Long> menuIds = roleMenus.stream().map(SysRoleMenu::getMenuId)
                .collect(Collectors.toList());
        SysRoleDTO roleDTO = new SysRoleDTO();
        BeanUtils.copyProperties(role,roleDTO);
        roleDTO.setMenuIds(menuIds);
        return roleDTO;
    }
}
